#include "BlockQueue.hpp"  // 阻塞队列
#include "Task.hpp"        // 计算任务类
#include <unistd.h>
#include <ctime>

// 消费者线程函数
void *Consumer(void *args)
{
    // 将void*转换为阻塞队列指针
    BlockQueue<Task> *bq = static_cast<BlockQueue<Task> *>(args);

    while (true)
    {
        // 从队列中取出任务（如果队列为空会阻塞）
        Task t = bq->pop();

        // 两种方式执行任务：
        // t.run();  // 直接调用run方法
        t();        // 通过重载的operator()执行

        // 打印任务处理结果
        std::cout << "处理任务: " << t.GetTask()           // 原始任务表达式
                  << " 运算结果是： " << t.GetResult()      // 计算结果
                  << " thread id: " << pthread_self()      // 线程ID
                  << std::endl;
        
        // 可选的处理延时
        // sleep(1);
    }
}

// 生产者线程函数
void *Productor(void *args)
{
    int len = opers.size();  // 可用运算符数量
    // 将void*转换为阻塞队列指针
    BlockQueue<Task> *bq = static_cast<BlockQueue<Task> *>(args);
    
    // 未使用的测试数据Xingshi111llkj/
    
    int x = 10;
    int y = 20;
    
    while (true)
    {
        // 随机生成计算任务的参数
        int data1 = rand() % 10 + 1;  // 生成1-10的随机数
        usleep(10);                   // 短暂延时，增加随机性
        int data2 = rand() % 10;      // 生成0-9的随机数
        char op = opers[rand() % len];// 随机选择运算符
        
        // 创建新任务
        Task t(data1, data2, op);

        // 将任务放入队列（如果队列满会阻塞）
        bq->push(t);
        
        // 打印生产信息
        std::cout << "生产了一个任务: " << t.GetTask() 
                  << " thread id: " << pthread_self() 
                  << std::endl;
                  
        sleep(1);  // 生产延时
    }
}

int main()
{
    // 初始化随机数种子
    srand(time(nullptr));

    // 创建阻塞队列
    // 注意：BlockQueue可以存储任何类型，这里存储Task对象
    BlockQueue<Task> *bq = new BlockQueue<Task>();
    
    // 创建3个消费者线程和5个生产者线程（3:2:1原则）
    pthread_t c[3], p[5];
    
    // 创建消费者线程
    for (int i = 0; i < 3; i++)
    {
        pthread_create(c + i, nullptr, Consumer, bq);
    }

    // 创建生产者线程
    for (int i = 0; i < 5; i++)
    {
        pthread_create(p + i, nullptr, Productor, bq);
    }

    // 等待所有消费者线程结束
    for (int i = 0; i < 3; i++)
    {
        pthread_join(c[i], nullptr);
    }
    
    // 等待所有生产者线程结束
    for (int i = 0; i < 5; i++)
    {
        pthread_join(p[i], nullptr);
    }
    
    // 清理资源
    delete bq;
    return 0;
}